#include "Codificador.h"

Codificador::Codificador(){}

void Codificador::codificarUnario(const unsigned int numero , Archivo *archivo,BitWrapper &b){

        unsigned int auxiliar = numero;
        auxiliar--;
        for(;auxiliar > 0;auxiliar--){
                b.writeBit(1,archivo);
        }
        b.writeBit(0,archivo);
}

unsigned int Codificador::decodificarUnario(Archivo *archivo,BitWrapper &b){

    unsigned int retorno = 2;
            while(!b.getBit(archivo));
            while(b.getBit(archivo))
                retorno++;
            return retorno;
}

void Codificador::codificarGamma(unsigned int numero, Archivo *a,BitWrapper &b){

        unsigned int cantBitsBin = 0;
        numero+=1;
        cantBitsBin = floor(log2(numero));
        //Codifico la parte unaria
        Codificador::codificarUnario(1+cantBitsBin,a,b);
        for(;cantBitsBin > 0;cantBitsBin--){
                b.writeBit((numero>>(cantBitsBin-1))&1,a);
        }
}


unsigned int Codificador::decodificarGamma(Archivo *a,BitWrapper &b){

        unsigned int valorUnario = 0;
        unsigned int cantidadBitsBinario = 0;
        unsigned int valorBinario = 0;
        valorUnario = Codificador::decodificarUnario(a,b);
        //cout<<"Valor unario: "<<valorUnario<<endl;
        cantidadBitsBinario = valorUnario-1;
        for( unsigned int i = cantidadBitsBinario; i>0 ; i--){
                if(b.getBit(a))
                        valorBinario+=pow(2,(i-1));
        }
        //cout<<"Cantidad  binario: "<<cantidadBitsBinario<<endl;
        return (pow(2,cantidadBitsBinario) + valorBinario)-1;
}

void Codificador::codificarDelta(unsigned int numero, Archivo *a,BitWrapper &b){
    numero+=1;
    unsigned int cantBitsBin = 0;
        cantBitsBin = floor(log2(numero));
        //Codifico la parte unaria
        Codificador::codificarGamma(1+cantBitsBin,a,b);
        for(;cantBitsBin > 0;cantBitsBin--) {
                b.writeBit((numero>>(cantBitsBin-1))&1,a);
        }
}

unsigned int Codificador::decodificarDelta(Archivo *a,BitWrapper &b){
        unsigned int valorGamma = 0;
        unsigned int cantidadBitsBinario = 0;
        unsigned int valorBinario = 0;
        valorGamma = Codificador::decodificarGamma(a,b);
        cantidadBitsBinario = valorGamma-1;
        for(unsigned int i = cantidadBitsBinario; i>0 ; i--){
                if(b.getBit(a))
                        valorBinario+=pow(2,(i-1));
        }
        return (pow(2,cantidadBitsBinario) + valorBinario)-1;
}

Codificador::~Codificador() {}
